#ifndef OSCTHULHUSERVER_H
#define OSCTHULHUSERVER_H

//#include "QMap"
#include "QHash"
#include "User.h"
#include "QString"
#include "ServerPacketListener.h"
#include "externals/includes/ip/UdpSocket.h"
#include "externals/includes/osc/OscReceivedElements.h"
#include "externals/includes/osc/OscOutboundPacketStream.h"
#include <QObject>
class ServerOSCThread;
class KeepAlive;
class StateSynchronization;
#include "ServerOSCThread.h"
#include "KeepAlive.h"
#include <QReadWriteLock>
#include "SyncObject.h"
#include "StateSynchronization.h"
#include "QDebug"
#include "QPointer"
#include "Constants.h"


class OSCthulhuServer
{
public:
    OSCthulhuServer(int serverPort, QString serverPassword);
    void createUser(const char* serverPassword,const char* userName,const char* userPassword,QString address,float port,QString publicPort);
    int getPort();

    User* getUser(QString userName);
    int getNumUsers();
    void disconnectUser(const char* serverPassword,const char* userName,const char* userPassword,float port);

    void sendAlive(int waitTime);
    void removeDead(int waitTime);
    void setUserAlive(QString userName);

    QString getServerPassword();

    bool addSyncObject(QString name,QString type,QString subtype);
    void removeSyncObject(QString name);
    void addSyncArg(QString name,QVariant* argValue);
    void setSyncArg(QString name,int argNum,QVariant* argValue,QString inputSync);
    void localSetSyncArg(QString name, int argNum,QVariant* argValue,QString inputSync);

    void finalizeSyncObject(QString name);
    void sendSyncObject(QString name);
    void sendSyncArg(QString name, int argNum,QString inputSync);
    void sendRemoveSyncObject(QString name);
    SyncObject* getSyncObject(QString name);
    QVariant* getSyncArg(QString name,QString argName);
    void sendStatesync();
    void sendToUsers(osc::OutboundPacketStream p);
    void multicastChatToUsers( osc::ReceivedMessage m, QString uN ); // send to everyone but yourself
    void changeUserPiece(QString user, QString piece);
    void cleanup(QString user, QString piece);
private:
    ServerOSCThread* oscThread;
    StateSynchronization* stateSync;
    int serverPort;
    QString serverPassword;
    QHash<QString, QPointer<User> > users;
    QHash<QString, QPointer<SyncObject> > syncObjects;
    QReadWriteLock lock,syncObjectLock;
    KeepAlive* keepAlive;
    char syncBuffer[SYNC_OUTPUT_BUFFER_SIZE];
    osc::OutboundPacketStream syncPacket;
};

class OSCthulhuServer;
#endif // OSCTHULHUSERVER_H
